﻿#include "MySqlApi.h"
#include <vector>
#include <string>

MySqlApi::MySqlApi(string ip, unsigned int port, string db, string user, string passwd)
{
    conninfo.hostname = ip;
    conninfo.Port = port;
    conninfo.username = user;
    conninfo.dbname = db;
    conninfo.passwd = passwd;

    IsConnect = false;
    m_strError = "";
}

MySqlApi::~MySqlApi()
{
    if (IsConnect)
    {
        mysql_close(&mysql); // 析构关闭连接
    }
}

bool MySqlApi::ConnDB()
{
    if (mysql_init(&mysql) == NULL)
    {
        m_strError = mysql_error(&mysql);
        printf("[%s:%d] %s\n", __FILE__, __LINE__, m_strError.c_str());
        return false;
    }

    // char ireadtimeout = 1 ;
    // int	error =	mysql_options(&mysql,MYSQL_OPT_RECONNECT,(char*)&ireadtimeout);

    if (mysql_real_connect(&mysql, conninfo.hostname.c_str(), conninfo.username.c_str(), conninfo.passwd.c_str(), conninfo.dbname.c_str(), conninfo.Port, NULL, 0) == NULL)
    {
        m_strError = mysql_error(&mysql);
        printf("[%s:%d] %s\n", __FILE__, __LINE__, m_strError.c_str());
        return false;
    }

    if (0 != mysql_query(&mysql, "SET NAMES utf8"))
    {
        m_strError = mysql_error(&mysql);
        return false;
    }

    if (0 != mysql_query(&mysql, "set global wait_timeout=1728000;"))
    {
        m_strError = mysql_error(&mysql);
        printf("[%s:%d] %s\n", __FILE__, __LINE__, m_strError.c_str());
        return false;
    }

    IsConnect = true;
    return true;
}

bool MySqlApi::ExecuteSql(const char *sql, int length)
{
    if (mysql_real_query(&mysql, sql, length) == 0)
    {
        return true; // mysql_affected_rows(&mysql);
    }
    else
    {
        // 如果失败，尝试重新连接并执行一次
        m_strError = mysql_error(&mysql);
        printf("MySQL Error: %s\n", m_strError.c_str());

        int errlen = m_strError.find("Duplicate entry"); // 这个错表示插入重复的 主键，可以忽略不重新执行；
        if (errlen == 0)
        {
            return true;
        }
    }

    return false;
}

bool MySqlApi::ExecuteSql(string strsql)
{
    if (mysql_real_query(&mysql, strsql.c_str(), strsql.length()) == 0)
    {
        return true; // mysql_affected_rows(&mysql);
    }
    else
    {
        // 如果失败，尝试重新连接并执行一次
        m_strError = mysql_error(&mysql);
        printf("MySQL Error: %s\n", m_strError.c_str());

        int errlen = m_strError.find("Duplicate entry"); // 这个错表示插入重复的 主键，可以忽略不重新执行；
        if (errlen == 0)
        {
            return true;
        }
    }

    return false;
}

bool MySqlApi::ExecuteSql(vector<string> sqlvec)
{
    if (sqlvec.size() <= 0)
    {
        return true;
    }

    mysql_autocommit(&mysql, 0); // 关闭自动提交
    vector<string>::iterator iter;
    for (iter = sqlvec.begin(); iter != sqlvec.end(); iter++)
    {
        string strSql = iter->c_str();
        // cout << strSql << endl;

        if (mysql_real_query(&mysql, strSql.c_str(), strSql.length()) == 0) //
        {
        }
        else
        {
            m_strError = mysql_error(&mysql);
            printf("事务错误--[%s]\n", m_strError.c_str());
            mysql_rollback(&mysql);
            return false;
        }
    }

    if (mysql_commit(&mysql) == 0)
    {
        // printf("事务成功\n");
    }
    else
    {
        // printf("事务失败\n");
        mysql_autocommit(&mysql, 1); // 关闭自动提交,也就是关闭事务
        mysql_rollback(&mysql);
        return false;
    }

    mysql_autocommit(&mysql, 1); // 关闭自动提交,也就是关闭事务
    return true;
}

bool MySqlApi::SelectSql(string sql, vector<map<string, string>> &Record)
{
    MYSQL_RES *m_res;
    // MYSQL_ROW m_row; // 标识返回数据一共

    if (mysql_real_query(&mysql, sql.c_str(), sql.length()) != 0)
    {
        m_strError = mysql_error(&mysql);
        printf("数据库错误2[%s]\n", m_strError.c_str());
        return false;
    }

    m_res = mysql_store_result(&mysql);
    if (m_res == NULL)
    {
        m_strError = mysql_error(&mysql);
        return false;
    }

    // int linenum=mysql_num_rows(m_res);  //获取行数

    int rownum = mysql_num_fields(m_res); // 获取列数
    MYSQL_FIELD *pfields = mysql_fetch_fields(m_res);
    map<string, string> mapTemp;
    while (MYSQL_ROW m_row = mysql_fetch_row(m_res))
    {
        for (int j = 0; j < rownum; j++)
        {
            string strTemp = (NULL == m_row[j]) ? "" : m_row[j];

            std::string fieldName(pfields[j].name, pfields[j].name_length);

            mapTemp[fieldName] = strTemp;

            printf("%s ", fieldName.c_str());

        }
        printf("\n");

        Record.push_back(mapTemp);
        mapTemp.clear();
    }
    mysql_free_result(m_res);

    return true;
}

std::string MySqlApi::GetMySqlError()
{
    return m_strError;
}

int MySqlApi::IsClose()
{
    return mysql_ping(&mysql);
}
